const Cell = @import("../cell.zig");

pub const SysEnergy = @This();

const E2F: f32 = 0.75;
const E2L: f32 = 2.0;

const MaxEnergy: u32 = 2500;
const MinEnergy: u32 = 1092;

const MaxFat: u32 = 80000;
const MinFat: u32 = 40000;

const MaxLife: u32 = 48000;
const MinLife: u32 = 40000;

const MaxIdleEnergyDrain: u32 = 300;
const MinIdleEnergyDrain: u32 = 100;

energy: f32, // 血糖
fat: f32, // 脂肪
life: f32, // 生命值
fatigue_line: f32, // 产生疲惫的基准线，每秒消耗脂肪能量高于该值，将积累疲惫值

fatigue_status: f32, // 疲惫状态，消耗脂肪时会造成疲惫
weak_status: f32, // 虚弱状态，消耗生命时会造成虚弱

max_energy: f32, // 血糖
max_fat: f32, // 脂肪
max_life: f32, // 生命值
idle_energy_drain: f32, // 静息能量消耗

energy_drained: f32,

cell: *Cell,

pub fn init(cell: *Cell) @This() {
    const tmp_energy: f32 = @floatFromInt(cell.rand.intRangeAtMost(u32, MinEnergy, MaxEnergy));
    const tmp_fat: f32 = @floatFromInt(cell.rand.intRangeAtMost(u32, MinFat, MaxFat));
    const tmp_life: f32 = @floatFromInt(cell.rand.intRangeAtMost(u32, MinLife, MaxLife));
    const _idle_energy_drain: f32 = @as(f32, @floatFromInt(cell.rand.intRangeAtMost(u32, MinIdleEnergyDrain, MaxIdleEnergyDrain))) / 100.0;

    return .{
        .cell = cell,
        .energy = tmp_energy,
        .max_energy = tmp_energy,
        .fat = tmp_fat,
        .max_fat = tmp_fat,
        .life = tmp_life,
        .max_life = tmp_life,
        .idle_energy_drain = _idle_energy_drain,
        .fatigue_line = _idle_energy_drain * 7.2,
        .fatigue_status = 0.0,
        .weak_status = 0.0,
        .energy_drained = 0.0,
    };
}

pub fn deinit(self: *@This()) void {
    _ = self;
}

pub fn keepAlive(self: *@This(), times: f32) void {
    self.energy_drained += times * self.idle_energy_drain;
}

pub fn recharge(self: *@This(), point: f32) void {
    var tmp_point = point;
    if (self.energy + point <= self.max_energy) {
        self.energy += point;

        return;
    } else {
        tmp_point -= self.max_energy - self.energy;

        self.energy = self.max_energy;
    }

    self.fat += tmp_point;
    if (self.fat > self.max_fat) {
        self.fat = self.max_fat;
    }
}

/// life耗尽，就意味着死亡，返回false
pub fn costEnergy(self: *@This()) void {
    const point = self.energy_drained;
    self.energy_drained = 0.0;

    var tmp_point = point;
    if (self.energy > 0 and self.energy >= point) {
        self.energy = self.energy - point;

        return;
    } else if (self.energy > 0) {
        tmp_point = point - self.energy;
        self.energy = 0;
    }

    tmp_point = tmp_point * 2.0;
    if (self.life >= tmp_point) {
        self.life = self.life - tmp_point;
        self.weak_status += tmp_point;

        return;
    } else {
        self.life = 0;

        self.cell.alive = false;
    }
}

/// life耗尽，就意味着死亡，返回false
pub fn costFat(self: *@This(), times: f32) void {
    const point = self.energy_drained;
    self.energy_drained = 0.0;

    const be_fatigue = point / times > self.fatigue_line;

    var tmp_point = point;
    if (self.fat > 0 and self.fat >= point) {
        self.fat = self.fat - point;

        if (be_fatigue) {
            self.fatigue_status += point;
        }

        return;
    } else if (self.fat > 0) {
        tmp_point = point - self.fat;

        if (be_fatigue) {
            self.fatigue_status += self.fat;
        }

        self.fat = 0;
    }

    if (self.energy >= tmp_point) {
        self.energy -= tmp_point;

        return;
    } else {
        tmp_point -= self.energy;

        self.energy = 0;
    }

    tmp_point = tmp_point * E2L;
    if (self.life >= tmp_point) {
        self.life = self.life - tmp_point;
        self.weak_status += tmp_point;

        return;
    } else {
        self.life = 0;

        self.cell.alive = false;
    }
}
